/******************** (C) COPYRIGHT 2011 STMicroelectronics ********************
 * File Name          : COMM_SERVER.c
 * Author             : MCD Application Team
 * Version            : V3.3.0
 * Date               : 21-March-2011
 * Description        : Custom HID demo main file
 ********************************************************************************
 * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
 * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME.
 * AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
 * INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
 * CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
 * INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
 *******************************************************************************/

/* Includes ------------------------------------------------------------------*/

#ifndef COMMUNI_SERVER_GLOBALS
#define COMMUNI_SERVER_GLOBALS
#include <includes.h>
#include "communi_server.h"
#include "communi_print.h"
#include "usb_desc.h"
#include "usb_lib.h"
#include "app_usb.h"
#include "PrimeMotor_Driver.h"
#include "TempControl_Driver.h"

static uint8_t CommuniRXdataHandling(uint8_t *SourcePoint, uint8_t *TargetPoint, uint16_t TargetNum, uint16_t *StaBuffer, uint8_t CommType);
static uint8_t USBRecdataCommand36_handling(uint8_t *SourcePoint, uint16_t Length, uint8_t *TargetPoint, uint16_t TargetNum, uint16_t *StaBuffer);
static uint8_t USBRecdataCommand37_handling(uint8_t *SourcePoint, uint16_t Length, uint8_t *TargetPoint, uint16_t TargetNum, uint16_t *StaBuffer);
static uint8_t USBRecdataCommand40_handling(uint8_t *SourcePoint, uint16_t Length, uint8_t *TargetPoint, uint16_t TargetNum, uint16_t *StaBuffer, uint8_t CommType);
static uint8_t USBRecdataCommand41_handling(uint8_t *SourcePoint, uint16_t Length, uint8_t *TargetPoint, uint16_t TargetNum, uint16_t *StaBuffer, uint8_t CommType);
static uint8_t USBRecdataCommand42_handling(uint8_t *SourcePoint, uint16_t Length, uint8_t *TargetPoint, uint16_t TargetNum, uint16_t *StaBuffer);
static uint8_t USBRecdataCommand43_handling(uint8_t *SourcePoint, uint16_t Length, uint8_t *TargetPoint, uint16_t TargetNum, uint16_t *StaBuffer);
static void CommunicationReturnMSGComposing(uint8_t *SourcePoint, uint8_t *TargetPoint, uint8_t returnCode, uint16_t *StaBuffer);
static void CommunicationReturnMSG_42(uint8_t *SourcePoint, uint8_t *TargetPoint, uint8_t returnCode, uint16_t *StaBuffer);

/// @brief USB通讯服务函数
/// @param  none
/// @return 状态信息
uint8_t Communi_USBserver(void)
{
    uint8_t CommDataStatus = CommDealReturnCode_Null;

    /* USB RX */
    CommDataStatus = CommuniRXdataHandling(USBRXBufferData, USBTXBufferData, USBTXBufferDataTOTNum, USBCommStatusBuffer, CommTypeOrd_USB); // 接收上位机数据处理

    /* USB TX */
    if (CommDataStatus & CommDealReturnCode_MsgTX)
        USBDateSendCOMM_handling(USBTXBufferData, USBCommStatusBuffer[GenCommStaBFOrd_TXDataNumber]); // 返回查询的数据到上位机

    /* End */
    USBRXBufferData[USBRXBufferDataTOTNum - 1] = COMMRecdataType_Null;
    return (CommDataStatus);
}

/// @brief RS485通讯服务函数
/// @param  none
/// @return 状态信息
uint8_t Communi_RS485server(void)
{
    uint8_t CommDataStatus = CommDealReturnCode_Null;
    uint16_t crcValue = 0;

    // 数据校验
    crcValue = Comm_CalCRC16(RS485RXBufferData, RS485RXBufferCount - 2);
    if(crcValue != ((RS485RXBufferData[RS485RXBufferCount - 2] << 8) | RS485RXBufferData[RS485RXBufferCount -1])){
        // 释放RS485总线
        OSSemPost((OS_EVENT *)App_Sem_RS485BUSIDLE);
        return (CommDataStatus);
    }
    if(RS485RXBufferData[0] == 0x01){       // 变频器数据
        PMotor_RecvHandle(RS485RXBufferData);
    }
    else if(RS485RXBufferData[0] == 0x02){  // 温控器数据
        TempCtl_RecvHandle(RS485RXBufferData);
    }
    return (CommDataStatus);
}

/// @brief RS232通讯服务函数
/// @param  none
/// @return 状态信息
uint8_t Communi_RS232server(void)
{
    uint8_t CommDataStatus = CommDealReturnCode_Null;

    /* RS232 RX */
    CommDataStatus = CommuniRXdataHandling(RS232RXBufferData, RS232TXBufferData, RS232TXBufferDataTOTNum, RS232CommStatusBuffer, CommTypeOrd_RS232); // 接收上位机数据处理

    /* 处理完成开始下一次 */
    RS232_Rx_DMA_Channel->TXNUM = RS232RXBufferDataTOTNum;
    DMA_EnableChannel(RS232_Rx_DMA_Channel, ENABLE);
    
    /* RS232 TX */
    if (CommDataStatus & CommDealReturnCode_MsgTX)
        RS232_DmaTransferData(RS232TXBufferData, RS232CommStatusBuffer[GenCommStaBFOrd_TXDataNumber]); // 返回查询的数据到上位机

    /* End */
    RS232RXBufferData[RS232RXBufferDataTOTNum - 1] = COMMRecdataType_Null;
    return (CommDataStatus);
}

/// @brief 接收数据处理函数
/// @param SourcePoint 接收数据缓冲
/// @param TargetPoint 发送数据缓冲
/// @param TargetNum 发送数据缓冲大小
/// @param StaBuffer 状态缓冲
/// @param CommType 通讯类型
/// @return 状态信息
static uint8_t CommuniRXdataHandling(uint8_t *SourcePoint, uint8_t *TargetPoint, uint16_t TargetNum, uint16_t *StaBuffer, uint8_t CommType){
    uint8_t CommDataStatus = CommDealReturnCode_Null;
    uint8_t deviceID = (uint8_t)share_parameterCfgData_st.baseData_st.DeviceAddr;
    uint16_t TempNumber;

    /* 判断串口屏 */ 
    if(SourcePoint[0]==0xA1 &&SourcePoint[1]==0xA2&&SourcePoint[2]==0xA3&&CommType==CommTypeOrd_RS232)
    {
        //内容长度
        TempNumber = SourcePoint[4];
        TempNumber <<= 8;
        TempNumber += SourcePoint[5];
        /* Check CRC checksum */
        if(SourcePoint[TempNumber+6+0]!=0xA1||SourcePoint[TempNumber+6+1]!=0xA2||SourcePoint[TempNumber+6+2]!=0xA3)
            return CommDealReturnCode_Null;

        switch (SourcePoint[3])
        {
        case 0x42://写
            CommDataStatus |= USBRecdataCommand42_handling(SourcePoint, TempNumber, TargetPoint, TargetNum, StaBuffer);
            break;
        case 0x43://读
            CommDataStatus |= USBRecdataCommand43_handling(SourcePoint, TempNumber, TargetPoint, TargetNum, StaBuffer);
            break;
        }
        return (CommDataStatus);
    }
    
    
    /* 匹配设备ID */
    if (SourcePoint[0] != deviceID)
        return (CommDealReturnCode_Null);
    /* 检测命令码范围合法 */
    if ((SourcePoint[1] < USBCommFunctionCodeRange_Min) || (SourcePoint[1] > USBCommFunctionCodeRange_Max)) // 指令不能超出USB指令的范围
        return (CommDealReturnCode_Null);

    /* Get Data Length */
    TempNumber = SourcePoint[2];
    TempNumber <<= 8;
    TempNumber += SourcePoint[3];
    TempNumber += CommPTCByteSize_STRPack;

    /* Check CRC checksum */
    uint16_t RecChecksum = CalBufferDataCRC161(SourcePoint, TempNumber);
    if (((RecChecksum & 0x00ff) != SourcePoint[TempNumber]) || (((RecChecksum >> 8) & 0x00ff) != SourcePoint[TempNumber + 1]))
        return (CommDealReturnCode_Null);

    /* Operation Action */
    TempNumber -= CommPTCByteSize_STRPack;
    if (SourcePoint[1] == COMMCommandType_Cfg36)
        CommDataStatus |= USBRecdataCommand36_handling(SourcePoint, TempNumber, TargetPoint, TargetNum, StaBuffer);
    else if (SourcePoint[1] == COMMCommandType_Cfg37)
        CommDataStatus |= USBRecdataCommand37_handling(SourcePoint, TempNumber, TargetPoint, TargetNum, StaBuffer);
    else if (SourcePoint[1] == COMMCommandType_Cfg38)
        CommDataStatus |= USBRecdataCommand37_handling(SourcePoint, TempNumber, TargetPoint, TargetNum, StaBuffer) | CommDealReturnCode_MemoryUpd;
    else if (SourcePoint[1] == COMMCommandType_Cfg40) // 新增命令，用于传输打印数据
        CommDataStatus |= USBRecdataCommand40_handling(SourcePoint, TempNumber, TargetPoint, TargetNum, StaBuffer, CommType);
    else if (SourcePoint[1] == COMMCommandType_Cfg41) // 新增命令，用于传输打印数据
        CommDataStatus |= USBRecdataCommand41_handling(SourcePoint, TempNumber, TargetPoint, TargetNum, StaBuffer, CommType);

    return (CommDataStatus);
}

/// @brief 从设备中读取数据
/// @param SourcePoint 数据源缓冲
/// @param Length 长度
/// @param TargetPoint 数据目标缓冲 
/// @param TargetNum 长度
/// @param StaBuffer 状态缓冲
/// @return 状态信息
static uint8_t USBRecdataCommand36_handling(uint8_t *SourcePoint, uint16_t Length, uint8_t *TargetPoint, uint16_t TargetNum, uint16_t *StaBuffer){
    uint8_t CommDataStatus = CommDealReturnCode_Null;
    uint8_t * RXBufferPoint = NULL;
    uint8_t * TXBufferPoint = NULL;
    uint16_t TempByteNum = 0;
    uint16_t CRCChecksum = 0;

    /* 指向内容区域 */
    RXBufferPoint = &SourcePoint[CommPTCByteSize_STRPack];
    TXBufferPoint = &TargetPoint[CommPTCByteSize_STRPack];
    /* 从数据库中读取数据 */
    if(DataBase_ProtocolContentRead(RXBufferPoint, Length, TXBufferPoint, &TempByteNum) == DEF_FALSE)
        return CommDealReturnCode_Null;
    /* 组织响应数据包 */
    TargetPoint[0] = SourcePoint[0];
    TargetPoint[1] = SourcePoint[1];
    TargetPoint[2] = (TempByteNum >> 8) & 0x00ff;
    TargetPoint[3] = TempByteNum & 0x00ff;
    TempByteNum += CommPTCByteSize_STRPack;
    /* 计算校验和 */
    CRCChecksum = CalBufferDataCRC161(TargetPoint, TempByteNum);
    TargetPoint[TempByteNum++] = CRCChecksum & 0x00ff;
    TargetPoint[TempByteNum++] = (CRCChecksum >> 8) & 0x00ff;
    StaBuffer[GenCommStaBFOrd_TXDataNumber] = TempByteNum;

    /* 配置返回状态 */
    CommDataStatus |= CommDealReturnCode_MsgTX;
    return (CommDataStatus);
}

/// @brief 往设备中写入数据
/// @param SourcePoint 数据源缓冲
/// @param Length 长度
/// @param TargetPoint 数据目标缓冲
/// @param TargetNum 长度
/// @param StaBuffer 状态缓冲
/// @return 状态信息
static uint8_t USBRecdataCommand37_handling(uint8_t *SourcePoint, uint16_t Length, uint8_t *TargetPoint, uint16_t TargetNum, uint16_t *StaBuffer){
    uint8_t CommDataStatus = CommDealReturnCode_Null;
    uint8_t * RXBufferPoint = NULL;

    /* 指向内容区域 */
    RXBufferPoint = &SourcePoint[CommPTCByteSize_STRPack];
    /* 往数据库中写入数据 */
    if(DataBase_ProtocolContentWrite(RXBufferPoint, Length) == DEF_FALSE)
        return CommDealReturnCode_Null;
    /* 组织响应数据包 */
    CommunicationReturnMSGComposing(SourcePoint, TargetPoint, CommReturnMSGCode_Success, StaBuffer);

    /* 配置返回状态 */
    CommDataStatus |= CommDealReturnCode_MsgTX | CommDealReturnCode_SpecialCfg;
    return (CommDataStatus);
}
/* 串口读 */
static uint8_t USBRecdataCommand43_handling(uint8_t *SourcePoint, uint16_t Length, uint8_t *TargetPoint, uint16_t TargetNum, uint16_t *StaBuffer){
    uint8_t CommDataStatus = CommDealReturnCode_Null;
    uint8_t * TXBufferPoint = NULL;
    uint8_t * RXBufferPoint = NULL;
    uint16_t TempByteNum = 0;
    uint32_t TempAddress = 0;
    uint16_t temCRC=0;

    RXBufferPoint = &SourcePoint[6];
    RXBufferPoint++;
    TempAddress  = (*(RXBufferPoint++)) << 16;
    TempAddress |= (*(RXBufferPoint++)) << 8;
    TempAddress |= (*(RXBufferPoint++));

    RXBufferPoint = &SourcePoint[6];
    TXBufferPoint = &TargetPoint[10];
    if(TempAddress != 0x0)
    {
        /* 从数据库中读取数据 */
        if(DataBase_ProtocolContentRead(RXBufferPoint, Length, TXBufferPoint, &TempByteNum) == DEF_FALSE)
            return CommDealReturnCode_Null;
    }
    else
    {
        /* 指向内容区域 */
        memcpy(TXBufferPoint, &share_RealTimeData_ckp, sizeof(share_RealTimeData_ckp));
        TempByteNum += sizeof(share_RealTimeData_ckp);
    }
    TargetPoint[0] = 0xA1;
    TargetPoint[1] = 0xA2;
    TargetPoint[2] = 0xA3;
    TargetPoint[3] = SourcePoint[3];//功能码
    TempByteNum+=4;//加地址
    TargetPoint[4] = (TempByteNum >> 8) & 0x00ff;
    TargetPoint[5] = TempByteNum & 0x00ff;
    TargetPoint[6] = SourcePoint[6];
    TargetPoint[7] = SourcePoint[7];
    TargetPoint[8] = SourcePoint[8];
    TargetPoint[9] = SourcePoint[9];
    TempByteNum+=6;//帧头+指令+内容长度
    TargetPoint[TempByteNum++] = 0xA1;
    TargetPoint[TempByteNum++] = 0xA2;
    TargetPoint[TempByteNum++] = 0xA3;
    temCRC = Comm_CalCRC16(&TargetPoint[0], TempByteNum);
    TargetPoint[TempByteNum++] = temCRC>>8 ;
    TargetPoint[TempByteNum++] = temCRC & 0xFF;
    StaBuffer[GenCommStaBFOrd_TXDataNumber] = TempByteNum;

    /* 配置返回状态 */
    CommDataStatus |= CommDealReturnCode_MsgTX;
    return (CommDataStatus);
}



/* 串口写 */
static uint8_t USBRecdataCommand42_handling(uint8_t *SourcePoint, uint16_t Length, uint8_t *TargetPoint, uint16_t TargetNum, uint16_t *StaBuffer){
    uint8_t CommDataStatus = CommDealReturnCode_Null;
    uint8_t * RXBufferPoint = NULL;

    /* 指向内容区域 */
    RXBufferPoint = &SourcePoint[6];
    /* 往数据库中写入数据 */
    if(DataBase_ProtocolContentWrite(RXBufferPoint, Length) == DEF_FALSE)
        return CommDealReturnCode_Null;
    /* 组织响应数据包 */
    CommunicationReturnMSG_42(SourcePoint, TargetPoint, CommReturnMSGCode_Success, StaBuffer);

    /* 配置返回状态 */
    CommDataStatus |= CommDealReturnCode_MsgTX | CommDealReturnCode_SpecialCfg;
    return (CommDataStatus);
}
static void CommunicationReturnMSG_42(uint8_t *SourcePoint, uint8_t *TargetPoint, uint8_t returnCode, uint16_t *StaBuffer)
{
    uint16_t TempByteNum = 0;
    uint16_t temCRC=0;
    /* Feedback */
    TargetPoint[TempByteNum++] = 0xA1;
    TargetPoint[TempByteNum++] = 0xA2;
    TargetPoint[TempByteNum++] = 0xA3;
    TargetPoint[TempByteNum++] = SourcePoint[3];
    TargetPoint[TempByteNum++] = 0x00;//内容长度
    TargetPoint[TempByteNum++] = 0x01;//内容长度
    TargetPoint[TempByteNum++] = returnCode;
    TargetPoint[TempByteNum++] = 0xA1;
    TargetPoint[TempByteNum++] = 0xA2;
    TargetPoint[TempByteNum++] = 0xA3;
    temCRC = Comm_CalCRC16(&TargetPoint[0], TempByteNum);
    TargetPoint[TempByteNum++] = temCRC>>8 ;
    TargetPoint[TempByteNum++] = temCRC & 0xFF;
    StaBuffer[GenCommStaBFOrd_TXDataNumber] = TempByteNum;
}

/// @brief 通讯响应消息组成
/// @param SourcePoint 数据源缓冲
/// @param TargetPoint 数据目标缓冲
/// @param returnCode 返回码
/// @param StaBuffer 状态缓冲
static void CommunicationReturnMSGComposing(uint8_t *SourcePoint, uint8_t *TargetPoint, uint8_t returnCode, uint16_t *StaBuffer)
{
    /* Feedback */
    TargetPoint[0] = SourcePoint[0];
    TargetPoint[1] = SourcePoint[1];

    TargetPoint[2] = 0;
    TargetPoint[3] = 1;
    TargetPoint[4] = returnCode;

    uint16_t CRCChecksum = CalBufferDataCRC161(TargetPoint, 5);
    TargetPoint[5] = CRCChecksum & 0x00ff;
    TargetPoint[6] = (CRCChecksum >> 8) & 0x00ff;
    StaBuffer[GenCommStaBFOrd_TXDataNumber] = 7;
}

static uint8_t USBRecdataCommand40_handling(uint8_t *SourcePoint, uint16_t Length, uint8_t *TargetPoint, uint16_t TargetNum, uint16_t *StaBuffer, uint8_t CommType)
{
    uint8_t CommDataStatus = CommDealReturnCode_Null;

    /* Check if Length Match */
    if (Length == 0)
    {
        return (CommDealReturnCode_Null);
    }
    else if (Length == 1) // 长度仅为1，表示特定功能开关
    {
        if (SourcePoint[CommPTCByteSize_STRPack] == 0)
        {
            CommPrintDataNum = 0; // 关闭打印传输
        }
    }
    else // 长度大于1，表示开始传输数据
    {
        CommPrintDataNum = SourcePoint[CommPTCByteSize_STRPack];
        if (CommPrintDataNum > CommData_PrintOnceNum)
            CommPrintDataNum = CommData_PrintOnceNum;
        uint8_t *RXLineAddr = &(SourcePoint[CommPTCByteSize_STRPack]) + 1; // 查看传输哪些线段
        for (uint8_t i = 0; i < CommPrintDataNum; i++)
        {
            CommData_PrintCurrentQueue[i] = *RXLineAddr;
            RXLineAddr++;
        }
    }

    return (CommDataStatus);
}

static uint8_t USBRecdataCommand41_handling(uint8_t *SourcePoint, uint16_t Length, uint8_t *TargetPoint, uint16_t TargetNum, uint16_t *StaBuffer, uint8_t CommType)
{
    uint8_t CommDataStatus = CommDealReturnCode_Null;

    /* Check if Length Match */
    if (Length == 0)
    {
        return (CommDealReturnCode_Null);
    }
    else if (Length == 1) // 长度仅为1，表示特定功能开关
    {
        if (SourcePoint[CommPTCByteSize_STRPack] == 1) // 手动合闸
        {
            PID_GeneratorSyncSwitch(PIDSyncAction_Manual);
        }
        if (SourcePoint[CommPTCByteSize_STRPack] == 2) // 自动合闸
        {
            PID_GeneratorSyncSwitch(PIDSyncAction_Auto);
        }
        if (SourcePoint[CommPTCByteSize_STRPack] == 3) // 分闸
        {
            PID_GeneratorSyncSwitch(PIDSyncAction_Open);
        }
    }
    else if (Length == 2) // 控制输入
    {
        switch (SourcePoint[CommPTCByteSize_STRPack])
        {
        case 0x01:
            /* code */
            break;

        case 0x02:
            /* code */
            break;

        case 0x03:
            /* code */
            break;

        default:
            break;
        }
    }

    return (CommDataStatus);
}

void USBDateSendCOMM_handling(uint8_t *Point, uint16_t DataNumber)
{
#ifdef EnableUSBDetectionOpt
    uint8_t USBDetectTiCnt = 0;
#endif

    uint8_t USBPrevXferTiCnt = 0;
    uint8_t USBEPTxStaTiCnt = 0;

    while (DataNumber)
    {
#ifdef EnableUSBDetectionOpt
        /* Check if USB Disconnect */
        if (GPIO_ReadInputDataBit(GPIOxPort_USBDetection, GPIOxBitx_USBDetection) == DEF_FALSE)
        {
            OSTimeDlyHMSM(0, 0, 0, 100);

            USBDetectTiCnt++;
            if (USBDetectTiCnt < 10) // 1s
                continue;

            PrevXferComplete = DEF_FALSE;
            break;
        }
        USBDetectTiCnt = 0;
#endif

        /* Feedback Same */
        if (PrevXferComplete)
        {
            OSTimeDlyHMSM(0, 0, 0, HIDPollingInterval);

            if (USBPrevXferTiCnt < 200) // 2s
                continue;

            PrevXferComplete = DEF_FALSE;
            break;
        }
        USBPrevXferTiCnt = 0;

        if (USB_GetEpTxSts(ENDP1) == 0)
        {
            OSTimeDlyHMSM(0, 0, 0, 500);

            USBEPTxStaTiCnt++;
            if (USBEPTxStaTiCnt < 10) // 5s
                continue;

            PrevXferComplete = DEF_FALSE;
            break;
        }
        USBEPTxStaTiCnt = 0;

        /* TX Running */
        PrevXferComplete = DEF_TRUE;
        if (DataNumber >= HIDMaxPacketSize)
        {
            /* Write the descriptor through the endpoint */
            USB_SilWrite(EP1_IN, Point, HIDMaxPacketSize);
            Point += HIDMaxPacketSize;
            DataNumber -= HIDMaxPacketSize;
        }
        else
        {
            uint8_t i, TempData[HIDMaxPacketSize];
            for (i = 0; i < DataNumber; i++)
                TempData[i] = *(Point++);
            for (i = DataNumber; i < HIDMaxPacketSize; i++)
                TempData[i] = 0xff;
            USB_SilWrite(EP1_IN, TempData, HIDMaxPacketSize);
            DataNumber = 0;
        }

#ifndef STM32F10X_CL
        USB_SetEpTxValid(ENDP1);
#endif /* STM32F10X_CL */
    }
}

#endif /*	COMMUNI_SERVER_GLOBALS	*/

/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/